package com.simple.gateway.pay.filter;

import com.simple.gateway.pay.strategy.BodySignStrategy;
import com.simple.gateway.pay.utils.SignUtil;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.gson.Gson;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.simple.common.entity.ResData;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.netflix.zuul.filters.support.FilterConstants;
import org.springframework.stereotype.Component;
import org.springframework.util.StreamUtils;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.Charset;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Map;


/**
 * 后置拦截器，用于加签
 */
@Slf4j
@Component
public class ResponseFilter extends ZuulFilter {

    @Autowired
    Gson gson;


    @Override
    public String filterType() {
        return FilterConstants.POST_TYPE;
    }

    @Override
    public int filterOrder() {
        return 0;
    }

    @Override
    public boolean shouldFilter() {
        HttpServletRequest request = RequestContext.getCurrentContext().getRequest();
        String requestURI = request.getRequestURI();
        if (requestURI.startsWith("/api/receiver")) {
            return false;
        }
        return true;
    }


    /**
     * 后置拦截器，用于加签，若为回调则不加签
     *
     * @return Object
     */
    @Override
    public Object run() {
        try {
            RequestContext requestContext = RequestContext.getCurrentContext();
            HttpServletRequest request = requestContext.getRequest();
            String uri = request.getRequestURI();
            HttpServletResponse response = requestContext.getResponse();
            response.setHeader("Access-Control-Allow-Origin", "*");
            if (isFilterUrl(uri)) {
                log.info("商户号【{}】响应处理==>>{},原因==>>路径【{}】为忽略验证路径",RequestFilter.MID.get(), "结束", uri);
                return null;
            }
            String body = getResBody(requestContext);
            if (StringUtils.isBlank(body)) {
                log.info("商户号为【{}】响应处理==>>{},原因为==>>{}", RequestFilter.MID.get(),"结束",  "请求异常，结束本次请求");
                return null;
            }
            log.info("商户号【{}】响应处理==>>{},内容为==>>{}", RequestFilter.MID.get(),"获取响应body成功",  body);
            ResData resData = objectMapper.readValue(body, ResData.class);
            if (!resData.isOk()) {
                requestContext.setResponseDataStream(new ByteArrayInputStream(body.getBytes()));
                log.info("商户号【{}】响应处理==>>{},原因为==>>{}", RequestFilter.MID.get(),"结束",  "无需加签");
                return null;

            }
            Long ts = System.currentTimeMillis() / 1000;
            Map<String, Object> signMap = new BodySignStrategy().responseSign((Map<String, Object>)resData.getData(), request, ts);
            String sign = SignUtil.createSign(signMap, RequestFilter.APIKEY.get(), RequestFilter.MID.get(),"响应处理");
            response.setHeader("version",request.getHeader("version"));
            response.setHeader("mid",request.getHeader("mid"));
            response.setHeader("ts",String.valueOf(ts));
            response.setHeader("signature",sign);
            requestContext.setResponseDataStream(new ByteArrayInputStream(objectMapper.writeValueAsString(resData).getBytes()));
            log.info("商户号【{}】响应处理==>>{},响应商户结果为==>>{}", RequestFilter.MID.get(),"结束",  gson.toJson(resData));
            return null;
        } catch (Exception e) {
            log.info("商户号【{}】响应处理==>>{},原因为==>>{}",RequestFilter.MID.get(), "异常", e.getMessage());
            return null;
        } finally {
            long endTime = System.currentTimeMillis();
            log.info("商户号【{}】网关处理==>>{},结束时间为==>>{},耗时==>>{}ms",RequestFilter.MID.get(), "结束",
                    LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")),
                    endTime - RequestFilter.TIME.get());
        }
    }


    /**
     * 获取响应body
     *
     * @param requestContext
     * @return
     */
    private String getResBody(RequestContext requestContext) {
        InputStream stream = requestContext.getResponseDataStream();
        String body = null;
        try {
            body = StreamUtils.copyToString(stream, Charset.forName("UTF-8"));
        } catch (IOException e) {
            log.info("商户号【{}】响应处理==>>{}异常结束,原因为==>>{}", RequestFilter.MID.get(),"获取响应body",  e.getMessage());
        }
        return body;
    }
    @Autowired
    ObjectMapper objectMapper;


    /**
     * 判断是否过滤路径
     *
     * @param uri
     * @return
     */
    private boolean isFilterUrl(String uri) {
        if (uri.contains("callback")
                || uri.contains("notify")
                || uri.contains("document")
                || uri.contains("nigeria/banks")
        ) {
            return true;
        }
        return false;
    }


}
